﻿//-----------------------------------------------------------------------
// <copyright file="CommandListDetailsViewModel.cs" author="Artak Mkrtchyan">
//     Creative Commons - GNU General Public License (http://creativecommons.org/licenses/GPL/2.0/
// </copyright>
// <author>Artak Mkrtchyan</author>
// <email>mkArtak@gmail.com</email>
// <date>01/09/2012</date>
//-----------------------------------------------------------------------
using ConsoleHoster.Common.Utilities;
using ConsoleHoster.Common.Utilities.Threading;
using ConsoleHoster.Common.ViewModel;
using ConsoleHoster.Model.Entities;
using ConsoleHoster.ViewModel.Entities;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;

namespace ConsoleHoster.ViewModel.ControlVM
{
	public class CommandListDetailsViewModel : ViewModelBase
	{
		private const string NewCommandNamePrefix = "New Command";

		private CommandDataViewModel selectedCommand;
		private readonly Lazy<ICommand> newCommandDataCommand;
		private ObservableCollection<CommandDataViewModel> commands;

		public CommandListDetailsViewModel(IEnumerable<CommandData> argCommands, IDispatcher argDispatcher, ILogger argLogger)
			: base(argDispatcher, new ComponentLogger("CommandListDetailsViewModel", argLogger))
		{
			this.Commands = argCommands == null ? new ObservableCollection<CommandDataViewModel>() : new ObservableCollection<CommandDataViewModel>(argCommands.Select(item => new CommandDataViewModel(item)));

			this.newCommandDataCommand = new Lazy<ICommand>(() => new RelayCommand(p =>
					{
						this.RunActionWithErrorHandling(() =>
						{
							if (this.Commands == null)
							{
								this.Commands = new ObservableCollection<CommandDataViewModel>();
							}

							List<string> tmpNewCommandsList = this.Commands.Where(item => item.Name.StartsWith(NewCommandNamePrefix)).Select(item => item.Name).ToList();
							string tmpName;
							int tmpNameIndex = 0;
							do
							{
								tmpName = String.Format("{0}{1}", NewCommandNamePrefix, tmpNameIndex++);
							} while (tmpNewCommandsList.Any(item => item.Equals(tmpName, StringComparison.InvariantCultureIgnoreCase)));

							CommandDataViewModel tmpNewCommand = new CommandDataViewModel
							{
								Name = tmpName
							};
							this.Commands.Add(tmpNewCommand);
							this.SelectedCommand = tmpNewCommand;
						});
					}));
		}

		public void RemoveCommand(CommandDataViewModel argCommandToRemove)
		{
			this.Commands.Remove(argCommandToRemove);
			if (this.SelectedCommand == argCommandToRemove)
			{
				this.SelectedCommand = null;
			}
		}

		private bool OnSelectedCommandChanging()
		{
			bool tmpResult = true;
			if (this.SelectedCommand != null && this.Commands.Contains(this.SelectedCommand) && !this.IsCommandValid(this.SelectedCommand))
			{
				tmpResult = false;
				this.ErrorMessage = "Command data is not valid";
			}
			return tmpResult;
		}

		private bool IsCommandValid(CommandDataViewModel argCommand)
		{
			return !String.IsNullOrWhiteSpace(argCommand.Name) && !String.IsNullOrWhiteSpace(argCommand.CommandText) && !this.Commands.Where(item => item.FullName.Equals(argCommand.FullName, StringComparison.InvariantCultureIgnoreCase) && item != argCommand).Any();
		}

		private void OnSelectedCommandChanged(CommandDataViewModel argOldValue)
		{
			if (this.ErrorMessage != null)
			{
				this.ErrorMessage = null;
			}
		}

		#region Properties
		public ICommand NewCommandDataCommand
		{
			get
			{
				return this.newCommandDataCommand.Value;
			}
		}

		public CommandDataViewModel SelectedCommand
		{
			get
			{
				return this.selectedCommand;
			}
			set
			{
				if (value != this.selectedCommand)
				{
					if (this.OnSelectedCommandChanging())
					{
						CommandDataViewModel tmpOldValue = this.selectedCommand;
						this.selectedCommand = value;
						this.OnSelectedCommandChanged(tmpOldValue);
					}
					this.NotifyPropertyChange("SelectedCommand");
				}
			}
		}

		public ObservableCollection<CommandDataViewModel> Commands
		{
			get
			{
				return this.commands;
			}
			set
			{
				if (value != this.commands)
				{
					this.commands = value;
					this.NotifyPropertyChange("Commands");
				}
			}
		}
		#endregion
	}
}
